home *** CD-ROM | disk | FTP | other *** search
- procedure BLOCK( FSYS:SYMSET; ISFUN:boolean; LEVEL:integer );
-
- type CONREC = record case TP: TYPES of
- INTS,CHARS,BOOLS: (I: INTEGER);
- REALS: (R: REAL)
- end;
-
- var DX : INTEGER; (* data allocation index *)
- PRT : INTEGER; (* T-index of this procedure *)
- PRB : INTEGER; (* B-index of this procedure *)
- X : INTEGER;
-
-
- procedure ENTERARRAY( TP: TYPES; L,H: INTEGER );
- begin
- if L > H then ERROR(27);
- if ( ABS(L) > XMAX ) OR ( ABS(H) > XMAX ) then begin
- ERROR(27);
- L := 0;
- H := 0;
- end;
- if A = AMAX then FATAL(4) else begin
- A := A+1;
- with ATAB[A] do begin
- INXTYP := TP;
- LOW := L;
- HIGH := H
- end;
- end;
- end; { ENTERARRAY }
-
- procedure ENTERBLOCK;
- begin
- if B = BMAX then FATAL(2) else begin
- B := B+1;
- BTAB[B].LAST := 0;
- BTAB[B].LASTPAR := 0;
- end;
- end; { ENTERBLOCK }
-
- procedure ENTERREAL(X: REAL);
- begin
- if C2 = C2MAX-1 then FATAL(3) else begin
- RCONST[C2+1] := X;
- C1 := 1;
- while RCONST[C1] <> X do C1 := C1+1;
- if C1 > C2 then C2 := C1
- end;
- end; { ENTERREAL }
-
- procedure SKIP( FSYS: SYMSET; N: INTEGER );
- begin
- ERROR(N);
- SKIPFLAG := TRUE;
- while NOT ( SY IN FSYS ) do INSYMBOL;
- if SKIPFLAG then ENDSKIP;
- end; { SKIP }
-
- procedure TEST(S1,S2: SYMSET; N: INTEGER);
- begin
- if NOT (SY IN S1) then SKIP(S1+S2,N);
- end; { TEST }
-
- procedure TESTSEMICOLON;
- begin
- if SY = SEMICOLON then INSYMBOL else begin
- ERROR(14);
- if SY IN [COMMA,COLON] then INSYMBOL
- end;
- TEST([IDENT]+BLOCKBEGSYS, FSYS, 6)
- end; { TESTSEMICOLON }
-
- procedure ENTER( ID: ALFA; K: OBJECT );
- var J,L: INTEGER;
- begin
- if T = TMAX then FATAL(1) else begin
- TAB[0].NAME := ID;
- J := BTAB[DISPLAY[LEVEL]].LAST;
- L := J;
- while TAB[J].NAME <> ID do J := TAB[J].LINK;
- if J <> 0 then ERROR(1) else begin
- T := T+1;
- with TAB[T] do begin
- NAME := ID;
- LINK := L;
- OBJ := K;
- TYP := NOTYP;
- REF := 0;
- LEV := LEVEL;
- ADR := 0;
- end;
- BTAB[DISPLAY[LEVEL]].LAST := T;
- end;
- end;
- end; { enter }
-
- function LOC( ID: ALFA ): INTEGER;
- var I,J: INTEGER; (* locate identifier, ID, in table *)
- begin
- I := LEVEL;
- TAB[0].NAME := ID; (* sentinel *)
- repeat
- J := BTAB[DISPLAY[I]].LAST;
- while TAB[J].NAME <> ID do J := TAB[J].LINK;
- I := I-1;
- until (I<0) OR (J<>0);
- if J = 0 then ERROR(0);
- LOC := J;
- end; { LOC }
-
- procedure ENTERVARIABLE;
- begin
- if SY = IDENT then begin
- ENTER(ID,VARIABLE);
- INSYMBOL;
- end else ERROR(2);
- end; { ENTERVARIABLE }
-
- procedure CONSTANT(FSYS: SYMSET; var C: CONREC);
- var X, SIGN: INTEGER;
- begin
- C.TP := NOTYP;
- C.I := 0;
- TEST(CONSTBEGSYS, FSYS, 50);
- if SY IN CONSTBEGSYS then begin
- if SY = CHARCON then begin
- C.TP := CHARS;
- C.I := INUM;
- INSYMBOL;
- end else begin
- SIGN := 1;
- if SY IN [PLUS,MINUS] then begin
- if SY = MINUS then SIGN := -1;
- INSYMBOL;
- end;
- if SY = IDENT then begin
- X := LOC(ID);
- if X <> 0 then if TAB[X].OBJ <> KONSTANT then ERROR(25)
- else begin
- C.TP := TAB[X].TYP;
- if C.TP = REALS then C.R := SIGN*RCONST[TAB[X].ADR]
- else C.I := SIGN*TAB[X].ADR
- end;
- INSYMBOL;
- end else if SY = INTCON then begin
- C.TP := INTS; C.I := SIGN*INUM;
- INSYMBOL
- end else if SY = REALCON then begin
- C.TP := REALS;
- C.R := SIGN * RNUM;
- INSYMBOL;
- end else SKIP(FSYS,50);
- end;
- TEST(FSYS, [], 6);
- end;
- end; { CONSTANT }
-
- procedure TYP( FSYS : SYMSET; var TP : TYPES; var RF, SZ : INTEGER);
- var X: INTEGER;
- ELTP: TYPES; ELRF: INTEGER;
- ELSZ, OFFSET, T0,T1: INTEGER;
-
- procedure ARRAYTYP(var AREF,ARSZ: INTEGER);
- var ELTP: TYPES;
- LOW, HIGH: CONREC;
- ELRF, ELSZ: INTEGER;
- begin
- CONSTANT([COLON,RBRACK,RPARENT,OFSY]+FSYS, LOW);
- if LOW.TP = REALS then begin
- ERROR(27);
- LOW.TP := INTS;
- LOW.I := 0;
- end;
- if SY = COLON then INSYMBOL else ERROR(13);
- CONSTANT([RBRACK,COMMA,RPARENT,OFSY]+FSYS, HIGH);
- if HIGH.TP <> LOW.TP then begin
- ERROR(27);
- HIGH.I := LOW.I;
- end;
- ENTERARRAY(LOW.TP, LOW.I, HIGH.I);
- AREF := A;
- if SY = COMMA then begin
- INSYMBOL;
- ELTP := ARRAYS;
- ARRAYTYP(ELRF,ELSZ)
- end else begin
- if SY = RBRACK then INSYMBOL else begin
- ERROR(12);
- if SY = RPARENT then INSYMBOL;
- end;
- if SY = OFSY then INSYMBOL else ERROR(8);
- TYP(FSYS,ELTP,ELRF,ELSZ);
- end;
- with ATAB[AREF] do begin
- ARSZ := (HIGH-LOW+1)*ELSZ;
- SIZE := ARSZ;
- ELTYP := ELTP;
- ELREF := ELRF;
- ELSIZE := ELSZ;
- end;
- end; { ARRAYTYP }
-
- begin { TYP }
- TP := NOTYP;
- RF := 0;
- SZ := 0;
- TEST(TYPEBEGSYS, FSYS, 10);
- if SY IN TYPEBEGSYS then begin
- if SY = IDENT then begin
- X := LOC(ID);
- if X <> 0 then with TAB[X] do
- if OBJ <> TYPE1 then ERROR(29) else begin
- TP := TYP;
- RF := REF;
- SZ := ADR;
- if TP = NOTYP then ERROR(30);
- end;
- INSYMBOL;
- end else
- if SY = ARRAYSY then begin
- INSYMBOL;
- if SY = LBRACK then INSYMBOL else begin
- ERROR(11);
- if SY = LPARENT then INSYMBOL
- end;
- TP := ARRAYS;
- ARRAYTYP(RF,SZ)
- end else begin { RECORDS }
- INSYMBOL;
- ENTERBLOCK;
- TP := RECORDS;
- RF := B;
- if LEVEL = LMAX then FATAL(5);
- LEVEL := LEVEL+1;
- DISPLAY[LEVEL] := B;
- OFFSET := 0;
- while NOT (SY IN FSYS-[SEMICOLON,COMMA,IDENT]+[ENDSY]) do begin
- if SY = IDENT then begin (* field section *)
- T0 := T;
- ENTERVARIABLE;
- while SY = COMMA do begin
- INSYMBOL;
- ENTERVARIABLE
- end;
- if SY = COLON then INSYMBOL else ERROR(5);
- T1 := T;
- TYP(FSYS+[SEMICOLON,ENDSY,COMMA,IDENT],ELTP,ELRF,ELSZ);
- while T0 < T1 do begin
- T0 := T0+1;
- with TAB[T0] do begin
- TYP := ELTP;
- REF := ELRF;
- NORMAL := TRUE;
- ADR := OFFSET;
- OFFSET := OFFSET + ELSZ;
- end;
- end;
- end;
- if SY <> ENDSY then begin
- if SY = SEMICOLON then INSYMBOL else begin
- ERROR(14);
- if SY = COMMA then INSYMBOL;
- end;
- TEST([IDENT,ENDSY,SEMICOLON], FSYS, 6);
- end;
- end;
- BTAB[RF].VSIZE := OFFSET;
- SZ := OFFSET;
- BTAB[RF].PSIZE := 0;
- INSYMBOL;
- LEVEL := LEVEL-1;
- end;
- TEST(FSYS, [], 6);
- end;
- end; { TYP }
-
- procedure PARAMETERLIST; (* formal parameter list *)
- var TP : TYPES;
- RF, SZ, X, T0 : INTEGER;
- VALPAR : BOOLEAN;
- begin
- INSYMBOL;
- TP := NOTYP;
- RF := 0;
- SZ := 0;
- TEST([IDENT, VARSY], FSYS+[RPARENT], 7);
- while SY in [IDENT,VARSY] do begin
- if SY <> VARSY then VALPAR := TRUE else begin
- INSYMBOL;
- VALPAR := FALSE
- end;
- T0 := T;
- ENTERVARIABLE;
- while SY = COMMA do begin
- INSYMBOL;
- ENTERVARIABLE;
- end;
- if SY = COLON then begin
- INSYMBOL;
- if SY <> IDENT then ERROR(2) else begin
- X := LOC(ID);
- INSYMBOL;
- if X <> 0 then with TAB[X] do
- if OBJ <> TYPE1 then ERROR(29) else begin
- TP := TYP;
- RF := REF;
- if VALPAR then SZ := ADR else SZ := 1
- end;
- end;
- TEST([SEMICOLON,RPARENT], [COMMA,IDENT]+FSYS, 14)
- end else ERROR(5);
- while T0 < T do begin
- T0 := T0+1;
- with TAB[T0] do begin
- TYP := TP;
- REF := RF;
- NORMAL := VALPAR;
- ADR := DX;
- LEV := LEVEL;
- DX := DX + SZ
- end
- end;
- if SY <> RPARENT then begin
- if SY = SEMICOLON then INSYMBOL else begin
- ERROR(14);
- if SY = COMMA then INSYMBOL
- end;
- TEST([IDENT,VARSY], [RPARENT]+FSYS, 6)
- end
- end; { while }
- if SY = RPARENT then begin
- INSYMBOL;
- TEST( [ SEMICOLON, COLON ], FSYS, 6)
- end else ERROR(4)
- end; { PARAMETERLIST }
-
- procedure CONSTDECLARATION;
- var C: CONREC;
- begin
- INSYMBOL;
- TEST( [IDENT], BLOCKBEGSYS, 2);
- while SY = IDENT do begin
- ENTER( ID, KONSTANT );
- INSYMBOL;
- if SY = EQL then INSYMBOL else begin
- ERROR(16);
- if SY = BECOMES then INSYMBOL;
- end;
- CONSTANT( [SEMICOLON,COMMA,IDENT]+FSYS, C );
- TAB[T].TYP := C.TP;
- TAB[T].REF := 0;
- if C.TP = REALS then begin
- ENTERREAL( C.R );
- TAB[T].ADR := C1;
- end else TAB[T].ADR := C.I;
- TESTSEMICOLON;
- end;
- end; { CONSTDECLARATION }
-
- procedure TYPEDECLARATION;
- var TP : TYPES;
- RF, SZ, T1: INTEGER;
- begin
- INSYMBOL;
- TEST( [IDENT], BLOCKBEGSYS, 2);
- while SY = IDENT do begin
- ENTER( ID, TYPE1 );
- T1 := T;
- INSYMBOL;
- if SY = EQL then INSYMBOL else begin
- ERROR(16);
- if SY = BECOMES then INSYMBOL
- end;
- TYP([SEMICOLON,COMMA,IDENT]+FSYS, TP, RF, SZ);
- with TAB[T1] do begin
- TYP := TP;
- REF := RF;
- ADR := SZ
- end;
- TESTSEMICOLON;
- end;
- end; { TYPEDECLARATION }
-
- procedure VARDECLARTION;
- var T0, T1, RF, SZ : INTEGER;
- TP : TYPES;
- begin
- INSYMBOL;
- while SY = IDENT do begin
- T0 := T;
- ENTERVARIABLE;
- while SY = COMMA do begin
- INSYMBOL;
- ENTERVARIABLE;
- end;
- if SY = COLON then INSYMBOL else ERROR(5);
- T1 := T;
- TYP( [SEMICOLON,COMMA,IDENT]+FSYS, TP, RF, SZ );
- while T0 < T1 do begin
- T0 := T0+1;
- with TAB[T0] do begin
- TYP := TP;
- REF := RF;
- LEV := LEVEL;
- ADR := DX;
- NORMAL := TRUE;
- DX := DX + SZ;
- end;
- end;
- TESTSEMICOLON;
- end;
- end; { VARDECLARTION }
-
- procedure PROCDECLARATION;
- var ISFUN: BOOLEAN;
- begin
- ISFUN := ( SY = FUNCSY );
- INSYMBOL;
- if SY <> IDENT then begin
- ERROR(2);
- ID := ' '
- end;
- if ISFUN then ENTER( ID, FUNKTION ) else ENTER( ID, PROZEDURE );
- TAB[T].NORMAL := TRUE;
- INSYMBOL;
- block( [SEMICOLON]+FSYS, ISFUN, LEVEL+1 );
- if SY = SEMICOLON then INSYMBOL else ERROR(14 );
- EMIT(32+ORD(ISFUN)) { EXIT }
- end; { procedure DECLARATION }
-
- (*---------------------------------------------------------STATEMENT--*)
-
- procedure STATEMENT( FSYS : SYMSET );
- var I : INTEGER;
- X : ITEM;
- procedure EXPRESSION( FSYS : SYMSET; var X: ITEM ); forward;
-
- procedure SELECTOR( FSYS: SYMSET; var V:ITEM );
- var X: ITEM; A,J: INTEGER;
- begin (* SY IN [LPARENT, LBRACK, PERIOD] *)
- repeat
- if SY = PERIOD then begin
- INSYMBOL; (* field selector *)
- if SY <> IDENT then ERROR(2) else begin
- if V.TYP <> RECORDS then ERROR(31)
- else begin (* search field identifier *)
- J := BTAB[V.REF].LAST;
- TAB[0].NAME := ID;
- while TAB[J].NAME <> ID do J := TAB[J].LINK;
- if J = 0 then ERROR(0);
- V.TYP := TAB[J].TYP;
- V.REF := TAB[J].REF;
- A := TAB[J].ADR;
- if A <> 0 then EMIT1(9,A);
- end;
- INSYMBOL;
- end;
- end else begin (* array selector *)
- if SY <> LBRACK then ERROR(11);
- repeat
- INSYMBOL;
- EXPRESSION(FSYS+[COMMA,RBRACK], X);
- if V.TYP <> ARRAYS then ERROR(28) else begin
- A := V.REF;
- if ATAB[A].INXTYP <> X.TYP then ERROR(26)
- else if ATAB[A].ELSIZE = 1 then EMIT1(20,A) else EMIT1(21,A);
- V.TYP := ATAB[A].ELTYP;
- V.REF := ATAB[A].ELREF;
- end;
- until SY <> COMMA;
- if SY = RBRACK then INSYMBOL else begin
- ERROR(12);
- if SY = RPARENT then INSYMBOL
- end;
- end;
- until NOT ( SY IN [ LBRACK, LPARENT, PERIOD ] );
- TEST( FSYS, [], 6 );
- end; { SELECTOR }
-
- procedure CALL( FSYS: SYMSET; I: INTEGER );
- var X : ITEM;
- LASTP, CP, K : INTEGER;
- begin
- EMIT1(18,I); (* mark stack *)
- LASTP := BTAB[TAB[I].REF].LASTPAR;
- CP := I;
- if SY = LPARENT then begin (* actual parameter list *)
- repeat
- INSYMBOL;
- if CP >= LASTP then ERROR(39) else begin
- CP := CP+1;
- if TAB[CP].NORMAL then begin (* value parameter *)
- EXPRESSION( FSYS+[COMMA,COLON,RPARENT], X );
- if X.TYP=TAB[CP].TYP then begin
- if X.REF <> TAB[CP].REF then ERROR(36)
- else if X.TYP = ARRAYS then EMIT1(22,ATAB[X.REF].SIZE)
- else if X.TYP = RECORDS
- then EMIT1(22,BTAB[X.REF].VSIZE)
- end else if (X.TYP=INTS) AND (TAB[CP].TYP=REALS)
- then EMIT1(26,0) else if X.TYP<>NOTYP then ERROR(36);
- end else begin (* variable parameter *)
- if SY <> IDENT then ERROR(2) else begin
- K := LOC(ID);
- INSYMBOL;
- if K <> 0 then begin
- if TAB[K].OBJ <> VARIABLE then ERROR(37);
- X.TYP := TAB[K].TYP;
- X.REF := TAB[K].REF;
- if TAB[K].NORMAL then EMIT2( 0,TAB[K].LEV, TAB[K].ADR )
- else EMIT2( 1,TAB[K].LEV, TAB[K].ADR );
- if SY IN [ LBRACK, LPARENT, PERIOD ]
- then SELECTOR(FSYS+[COMMA,COLON,RPARENT], X);
- if ( X.TYP<>TAB[CP].TYP ) OR ( X.REF<>TAB[CP].REF )
- then ERROR(36);
- end;
- end;
- end;
- end;
- TEST( [COMMA,RPARENT], FSYS, 6 );
- until SY <> COMMA;
- if SY = RPARENT then INSYMBOL else ERROR(4);
- end;
- if CP < LASTP then ERROR(39); (* too few actual parameters *)
- EMIT1( 19, BTAB[TAB[I].REF].PSIZE-1 );
- if TAB[I].LEV < LEVEL then EMIT2( 3, TAB[I].LEV, LEVEL )
- end; { CALL }
-
- function RESULTTYPE( A,B : TYPES ): TYPES;
- begin
- if ( A > REALS ) OR ( B > REALS ) then begin
- ERROR(33);
- RESULTTYPE := NOTYP;
- end else if (A=NOTYP) OR (B=NOTYP) then RESULTTYPE := NOTYP
- else if A=INTS then if B=INTS then RESULTTYPE := INTS
- else begin
- RESULTTYPE := REALS;
- EMIT1(26,1);
- end else begin
- RESULTTYPE := REALS;
- if B=INTS then EMIT1(26,0)
- end;
- end; { RESULTTYPE }